package g11.dao;

import g11.model.Employee;
import g11.model.Patient;
import g11.model.PatientAssignment;

import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class PatientAssignmentDAOImpl implements PatientAssignmentDAO {

	private Session session;

	public Session getSession() {
		return this.session;
	}

	public void cleanup() {
		if (session.isOpen())
			session.close();
		// HibernateUtil.shutdown();
	}

	public PatientAssignmentDAOImpl() {

	}

	public void CreatePatientAssignment(Employee doctor, Patient patient,
			byte permission) throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		PatientAssignment patientAssignment = new PatientAssignment();
		patientAssignment.setDoctorId(doctor.getId());
		patientAssignment.setPatientId(patient.getId());
		patientAssignment.setPermission(permission);
		Transaction tran = null;
		try {
			tran = session.beginTransaction();
			session.save(patientAssignment);
			tran.commit();

		} catch (HibernateException e) {
			tran.rollback();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
	}

	public void DeletePatientAssignment(Employee doctor, Patient patient)
			throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		PatientAssignment patientAssignment = new PatientAssignment();
		patientAssignment.setDoctorId(doctor.getId());
		patientAssignment.setPatientId(patient.getId());
		Transaction tran = null;
		try {
			tran = session.beginTransaction();
			patientAssignment = (PatientAssignment) session
					.merge(patientAssignment);
			session.delete(patientAssignment);
			tran.commit();
		} catch (HibernateException e) {
			tran.rollback();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}

	}

	public byte getPermission(Employee doctor, Patient patient)
			throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		byte permission = -1;
		PatientAssignment patientAssignment = new PatientAssignment();
		List<PatientAssignment> patientAssignmentList = new ArrayList<PatientAssignment>();
		try {
			Query q;
			q = session
					.createQuery("from PatientAssignment as p where p.doctorId=? and p.patientId=?");
			q.setInteger(0, doctor.getId());
			q.setInteger(1, patient.getId());
			patientAssignmentList = q.list();
			if (patientAssignmentList.size() > 0) {
				patientAssignment = patientAssignmentList.get(0);
				permission = patientAssignment.getPermission();
			}
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return permission;
	}

	public List<PatientAssignment> getPatientAssignmentByDoctorAndPermission(
			Employee doctor, byte permission) throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		List<PatientAssignment> patientAssignmentList = new ArrayList<PatientAssignment>();
		try {
			Query q;
			q = session
					.createQuery("from PatientAssignment as p where p.doctorId=? and p.permission=?");
			q.setInteger(0, doctor.getId());
			q.setInteger(1, permission);
			patientAssignmentList = q.list();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return patientAssignmentList;
	}

	/*
	 * this method was moved here from PatientDaoImpl this method gives back all
	 * patients either the doctor is default to or read only
	 */
	public List<Patient> getAllPatient(Employee doctor) throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		List<Patient> patientList = new ArrayList<Patient>();
		try {
			String hql = "select distinct p from Patient p join p.patientAssignmentSet pa where pa.doctorId=?";
			Query q = session.createQuery(hql);
			q.setInteger(0, doctor.getId());
			patientList = q.list();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return patientList;
	}

	public List<Patient> getPatientByDoctorBelongTo(Employee doctor)
			throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		List<Patient> patientList = new ArrayList<Patient>();
		// byte permission =0;//when belong to
		try {
			Query q;
			q = session
					.createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission= 0 and pa.doctorId=?");
			q.setInteger(0, doctor.getId());
			patientList = q.list();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return patientList;
	}

	public List<Patient> getPatientByDoctorReadOnly(Employee doctor)
			throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		List<Patient> patientList = new ArrayList<Patient>();
		// byte permission =1; //when read only
		try {
			Query q;
			q = session
					.createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission= 1 and pa.doctorId=?");
			q.setInteger(0, doctor.getId());
			patientList = q.list();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return patientList;
	}

	/*
	 * the patients should be the doctor's default patientsso we do
	 * getPatientByDoctorBelongTo(Employee doctor) first; then query the name
	 * from this patientlist
	 */
	public List<Patient> searchBelongToPatientForDoctor(String doctorId,
			Integer searchType, String searchContent) throws DAOException {

		this.session = HibernateUtil.getSessionFactory().openSession();
		List<Patient> patientList = new ArrayList<Patient>();
		try {
			Query q = session.createQuery("select p from Patient p");
			switch (searchType) {
			case 0:
				q = session
						.createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission= 0 and pa.doctorId=? and lower(p.name) like ?");
				break;
			// case 1:
			// q = session
			// .createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission= 0 and pa.doctorId=? and lower(p.lastVisitTime) like ?");
			// break;
			case 1:
				q = session
						.createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission= 0 and pa.doctorId=? and lower(p.ohip) like ?");
				break;
			}
			q.setInteger(0, Integer.valueOf(doctorId));
			String temp = "%" + searchContent.toLowerCase() + "%";
			q.setString(1, temp);
			patientList = q.list();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return patientList;
	}

	public List<Patient> searchReadOnlyPatientForDoctor(String doctorId,
			Integer searchType, String searchContent) throws DAOException {

		this.session = HibernateUtil.getSessionFactory().openSession();
		List<Patient> patientList = new ArrayList<Patient>();
		try {
			Query q = session.createQuery("select p from Patient p");
			switch (searchType) {
			case 0:
				q = session
						.createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission= 1 and pa.doctorId=? and lower(p.name) like ?");
				break;
			// case 1:
			// q = session
			// .createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission= 1 and pa.doctorId=? and lower(p.lastVisitTime) like ?");
			// break;
			case 1:
				q = session
						.createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission= 1 and pa.doctorId=? and lower(p.ohip) like ?");
				break;
			}
			q.setInteger(0, Integer.valueOf(doctorId));
			String temp = "%" + searchContent.toLowerCase() + "%";
			q.setString(1, temp);
			patientList = q.list();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return patientList;

	}

	public List<Employee> getAllNotAssignedDoctorListForPatient(Patient patient)
			throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		List<Employee> employeeList = new ArrayList<Employee>();
		try {
			Query q;
			q = session
					.createQuery("select distinct e from Employee e where e.type=1 and e not in (select e from Employee e join e.patientAssignmentSet pa where (pa.patientId= ? and pa.permission=0))");
			q.setInteger(0, patient.getId());
			employeeList = q.list();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return employeeList;
	}

	@Override
	public Integer getDefaultDoctorIdByPatientId(Integer patientId)
			throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		Integer defaultDoctorId = -1;
		try {
			String hql = "select p.doctorId from PatientAssignment as p where p.patientId=? and p.permission=0";
			Query q = session.createQuery(hql);
			q.setInteger(0, patientId);
			if (q.list().size() > 0) {
				defaultDoctorId = (Integer) q.list().get(0);
			}
		} catch (HibernateException e) {
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return defaultDoctorId;
	}

	@Override
	public void deletePatientAssignmentByAssignment(
			PatientAssignment patientAssignment) throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		Transaction tran = null;
		try {
			tran = session.beginTransaction();
			patientAssignment = (PatientAssignment) session
					.merge(patientAssignment);
			session.delete(patientAssignment);
			tran.commit();
		} catch (HibernateException e) {
			tran.rollback();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
	}

	@Override
	public void createPatientAssignmentByAssignment(
			PatientAssignment patientAssignment) throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		Transaction tran = null;
		try {
			tran = session.beginTransaction();
			session.save(patientAssignment);
			tran.commit();

		} catch (HibernateException e) {
			tran.rollback();
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
	}

	@Override
	public List<Patient> searchBelongToPatientForDoctorByLastVisitDate(
			Employee doctor, Date lastVisitDate) throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		List<Patient> patientList = new ArrayList<Patient>();
		try {
			Query q = session
					.createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission=0 and pa.doctorId=? and p.lastVisitTime=?");
			q.setInteger(0, doctor.getId());
			q.setDate(1, lastVisitDate);
			patientList = q.list();
		} catch (HibernateException e) {
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return patientList;
	}

	@Override
	public List<Patient> searchReadOnlyPatientForDoctorByLastVisitDate(
			Employee doctor, Date lastVisitDate) throws DAOException {
		this.session = HibernateUtil.getSessionFactory().openSession();
		List<Patient> patientList = new ArrayList<Patient>();
		try {
			Query q = session
					.createQuery("select p from Patient p join p.patientAssignmentSet pa where pa.permission=1 and pa.doctorId=? and p.lastVisitTime=?");
			q.setInteger(0, doctor.getId());
			q.setDate(1, lastVisitDate);
			patientList = q.list();
		} catch (HibernateException e) {
			throw new DAOException(e.getMessage());
		} finally {
			if (session.isOpen())
				session.close();
		}
		return patientList;
	}
}